package com.qs.education.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.qs.education.bean.beans.EducationAdminResponse;
import com.qs.education.bean.entity.EducationPermission;
import com.qs.education.bean.entity.EducationRole;
import com.qs.education.bean.utils.PasswordUtils;
import com.qs.education.service.IAdminService;


/**
 * 
 * @class MyShiroRealm.java
 * @author Arwen Liu
 * @description 自定义realm 完成用户的验证和授权	
 * @date 2018-10-24
 */

public class MyShiroRealm extends AuthorizingRealm {

	@Autowired
	private IAdminService iAdminService;
	
	//权限授权认证
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
	    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
	    EducationAdminResponse user  = (EducationAdminResponse)principals.getPrimaryPrincipal();
	    System.out.println(user.getRoles().toString());
	    if(user != null){
	    	try {
	    		//这个地方从数据中查询用户，并且关联查询出用户对应的角色以及权限 ，实现权限的认证
	    		EducationAdminResponse userWithRoleAndPermission = iAdminService.findAdminByName(user.getName());
	    		  System.out.println(userWithRoleAndPermission.getRoles().toString());
				if(null != userWithRoleAndPermission){
					 for(EducationRole role : userWithRoleAndPermission.getRoles()){
						 if(null != role){
							 authorizationInfo.addRole(role.getName());
							 for(EducationPermission p : role.getPermissions()){
								 if(null != p){
									 authorizationInfo.addStringPermission(p.getPermission());
								 }
							 }
						 }
				        
				    }
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
	    }
	    
	   
	    return authorizationInfo;
	}

	
	// 登录认证
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
	        throws AuthenticationException {
	    //获取用户的输入的用户名.
	    String name = (String)token.getPrincipal();
	    //输入的密码
	    String password = new String((char[])token.getCredentials());
	    //通过username从数据库中查找 User对象
	    EducationAdminResponse educationAdmin = iAdminService.findAdminByName(name); 
	    if(educationAdmin == null){
	        //return null;
	    	 throw new UnknownAccountException("账户不存在");
	    }
	    //验证密码
	    if(!educationAdmin.getPassword().equals(PasswordUtils.encodPassword(password))){
	    	throw new IncorrectCredentialsException("密码不正确");
	    }
	    /*SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
        user, //用户名
        user.getPassword(), //密码
        getName()  //realm name
	    );*/
	    /**
		 * 参数详解
		 * 第一个参数principal ：认证的实体信息。可以是username,也可以是用户的实体类对象
		 * 第二个参数hashedCredentials：是从数据库中获取的密码
		 * 第三个参数credentialsSalt：盐值，它的作用就是，即是两个人的原明文密码一样，可以通过这个值的控制，使加密后的密码不一样(一般可以使用username或者userid作为盐值)
		 * 第四个参数realmName: 当前 Realm 对象的 name调用父类的getName()方法即可
		 */
	    //第三个参数可以使用用户名作为盐
	    //ByteSource credentialsSalt = ByteSource.Util.bytes(name);
	    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
	            educationAdmin, //用户名
	            educationAdmin.getPassword(), //密码
	            null,
	            getName()  //realm name
	    );
	    return authenticationInfo;
	    //验证不正确
	}
	
	public static void main(String[] args) {
		//加密的方式
		String algorithmName = "MD5";
		//需要加密的字符串
		Object source = "123456";
		
		//盐值，它的作用就是，即是两个人的原明文密码一样，可以通过这个值的控制，使加密后的密码不一样
		Object salt = null;
		
		//需要加密的次数
		int hashIterations = 1;
		
		Object result = new SimpleHash(algorithmName, source, salt, hashIterations);
		System.out.println(result.toString());
	}

}
